#ifndef X28_H
#define X28_H

#include "common.h"

// Shape
template <AllegroVersion version>
struct x28
{
    uint16_t type;
    uint8_t subtype;
    uint8_t layer;
    
    uint32_t k;
    uint32_t un1;
    
    // Points to one of: header value, `x04`, `x2B`, `x2D`
    uint32_t ptr1;
    
    // Null?
    uint32_t un2;
    
    // Points to `x28`, `x2D`, or `x33`
    uint32_t next;
    
    // Points to `x05` or `x09` (much more frequently `x09`)
    uint32_t ptr3;
    
    // Points to `x34`?
    uint32_t ptr4;
    
    // Line segments that form shape (x01, x15, x16, x17)
    uint32_t first_segment_ptr;
    
    // Null?
    uint32_t un3;
    
    // Has a few random bits set?
    uint32_t un4;
    
    // Points to `x26`, `x2C`
    
    // Points to `x03`
    uint32_t ptr6;
    
    uint32_t ptr7_16x;
    
    // Bounding box
    int32_t coords[4];
    
    uint32_t TAIL;
    operator x28<A_174>() const;
    static constexpr AllegroVersion versions[1] = {A_172};
};

#if __cplusplus >= 202002L
template <AllegroVersion version> requires(version >= A_172)
struct x28<version>
{
    uint16_t type;
    uint8_t subtype;
    uint8_t layer;

    uint32_t k;
    uint32_t un1;

    // Points to one of: header value, `x04`, `x2B`, `x2D`
    uint32_t ptr1;

    // Null?
    uint32_t un2;

    uint32_t un5[2];

    // Points to `x28`, `x2D`, or `x33`
    uint32_t next;

    // Points to `x05` or `x09` (much more frequently `x09`)
    uint32_t ptr3;

    // Points to `x34`?
    uint32_t ptr4;

    // Line segments that form shape (x01, x15, x16, x17)
    uint32_t first_segment_ptr;

    // Null?
    uint32_t un3;

    // Has a few random bits set?
    uint32_t un4;

    // Points to `x26`, `x2C`
    uint32_t ptr7;

    // Points to `x03`
    uint32_t ptr6;

    // Bounding box
    int32_t coords[4];

    uint32_t TAIL;
    operator x28<A_174>() const;
    static constexpr AllegroVersion versions[1] = {A_172};
};
#else
template <> struct x28<A_172>
{
    uint16_t type;
    uint8_t subtype;
    uint8_t layer;

    uint32_t k;
    uint32_t un1;

    // Points to one of: header value, `x04`, `x2B`, `x2D`
    uint32_t ptr1;

    // Null?
    uint32_t un2;

    uint32_t un5[2];

    // Points to `x28`, `x2D`, or `x33`
    uint32_t next;

    // Points to `x05` or `x09` (much more frequently `x09`)
    uint32_t ptr3;

    // Points to `x34`?
    uint32_t ptr4;

    // Line segments that form shape (x01, x15, x16, x17)
    uint32_t first_segment_ptr;

    // Null?
    uint32_t un3;

    // Has a few random bits set?
    uint32_t un4;

    // Points to `x26`, `x2C`
    uint32_t ptr7;

    // Points to `x03`
    uint32_t ptr6;

    // Bounding box
    int32_t coords[4];

    uint32_t TAIL;
    operator x28<A_174>() const;
    static constexpr AllegroVersion versions[1] = {A_172};
};
template <> struct x28<A_174> : x28<A_172> {};
#endif

#endif // X28_H
